package main

import "fmt"

// 对表达式中涉及的对象进行定义
type SmartHomeContext struct {
	deviceStates map[string]string
	sensorValues map[string]float64
}

type Context interface {
	GetDeviceState(deviceID string) string
	GetSensorValue(sensorID string) float64
}

// 关键组件，定义表达式必须有方法进行解释
type Expression interface {
	Interpret(ctx Context) bool
}

// 以下为各解释器
type EqualsExpression struct {
	DeviceID string
	Value    string
}

func (e *EqualsExpression) Interpret(ctx Context) bool {
	return ctx.GetDeviceState(e.DeviceID) == e.Value
}

type GreaterThanExpression struct {
	SensorID string
	Value    float64
}

func (e *GreaterThanExpression) Interpret(ctx Context) bool {
	return ctx.GetSensorValue(e.SensorID) > e.Value
}

type AndExpression struct {
	Left, Right Expression
}

func (e *AndExpression) Interpret(ctx Context) bool {
	return e.Left.Interpret(ctx) && e.Right.Interpret(ctx)
}

type OrExpression struct {
	Left, Right Expression
}

func (e *OrExpression) Interpret(ctx Context) bool {
	return e.Left.Interpret(ctx) || e.Right.Interpret(ctx)
}

func (c *SmartHomeContext) GetDeviceState(deviceID string) string {
	return c.deviceStates[deviceID]
}

func (c *SmartHomeContext) GetSensorValue(sensorID string) float64 {
	return c.sensorValues[sensorID]
}

func main() {
	// 初始化上下文数据
	ctx := &SmartHomeContext{
		deviceStates: map[string]string{
			"卧室灯": "on",
			"浴室灯": "off",
		},
		sensorValues: map[string]float64{
			"温度传感器": 26.5,
			"湿度传感器": 45.0,
		},
	}

	// 构建表达式树：(卧室灯 == on) AND (温度传感器 > 25)，其实应该先将字符串转为表达式树，但着纯粹是个函数匹配就偷懒了
	expr := &AndExpression{
		Left:  &EqualsExpression{DeviceID: "卧室灯", Value: "on"},
		Right: &GreaterThanExpression{SensorID: "温度传感器", Value: 25},
	}

	result := expr.Interpret(ctx)
	fmt.Println("卧室等是否关闭且温度大于25度? ", result)

}
